import { ref, Ref } from 'vue'

class WebSocketService {
    private wsUrl: string
    private maxRetryAttempts: number = 3
    private currentRetryAttempt: number = 0
    private websocketServer: Ref<boolean> = ref(false)
    private websocket: WebSocket | null = null

    constructor(wsUrl: string) {
        this.wsUrl = wsUrl
        this.connect()
    }

    private log = (...args: any[]): void => {
        if (process.env.NODE_ENV === 'development') {
            console.log(...args)
        }
    }

    private connect = (): void => {
        this.websocket = new WebSocket(this.wsUrl)

        this.websocket.onopen = () => {
            this.log('WebSocket connection established')
            this.websocketServer.value = true
            this.currentRetryAttempt = 0

            this.onOpen()

            this.sendHeartbeat()
        }

        this.websocket.onclose = (event) => {
            this.log('WebSocket connection closed', event.reason)
            this.websocketServer.value = false
            this.retryConnection()
        }

        this.websocket.onmessage = (event) => {
            const message = JSON.parse(event.data)
            this.log('Received data from server', message)
            this.handleMessage(message)
        }
    }

    private sendHeartbeat = (): void => {
        setInterval(() => {
            if (this.websocketServer.value && this.websocket?.readyState === WebSocket.OPEN) {
                this.log('Sending heartbeat')
                this.websocket.send('ping')
            }
        }, 50000)
    }

    private retryConnection = (): void => {
        if (this.currentRetryAttempt < this.maxRetryAttempts) {
            setTimeout(() => {
                this.log(`Attempting to reconnect, attempt ${this.currentRetryAttempt + 1}`)
                this.connect()
                this.currentRetryAttempt++
            }, 5000)
        } else {
            console.warn(`Maximum retry attempts reached (${this.maxRetryAttempts}), failed to connect.`)
        }
    }

    /**
     * WebSocket连接成功后执行的操作
     */
    onOpen = (): void => {
        this.log('WebSocket is now open and ready to send data')
    }

    onClose = (): void => {
        // 手动关闭ws连接
        this.websocket?.close()
        this.log('WebSocket connection closed')
    }

    /**
     * 发送消息
     * @param message 消息内容
     */
    sendMessage = (message: anyObj): void => {
        if (this.websocket && this.websocket.readyState === WebSocket.OPEN && message) {
            const data = JSON.stringify(message)
            this.websocket.send(data)
        } else {
            console.warn('WebSocket is not open. Unable to send message.')
        }
    }

    /**
     * 处理接收到的消息
     * @param message 接收到的消息(json已解码)
     */
    handleMessage = (message: any): void => {
        this.log(message)
    }
}

export default WebSocketService
